home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
011
/
xlt86.lbr
/
XLT86.AQM
/
XLT86.ASM
Wrap
Assembly Source File
|
1979-12-31
|
41KB
|
2,769 lines
;*******************************************************
;
; XLT86
;
; Translates Intel 8080 assembly language source code
; to Intel 8086 assembly language source code.
;
; 11/11/84 Frank J. Zerilli
;
VERS EQU 106
;
;*******************************************************
;
; XLT86 processes lines with the exclamation point
; statement separator correctly. It strips trailing
; blanks or tabs from lines. It replaces initial
; asterisks in lines with semicolons. It provides
; several options to format the output file for best
; appearance.
;
; This program gives the choice of converting the
; case of instructions to upper or lower case or of
; trying to preserve the case of instructions.
;
; An activity dot is printed on the console for
; every 100 lines of input processed.
;
;
;
; Command line:
;
; XLT86 [d:]srcfile[.typ] [d:destfile.typ]
;
; All parameters in brackets are optional, and, if
; omitted, the default values are:
;
; Source file-type -- ASM
; Destination file-type -- A86
; Destination file-name -- same as the source file-name
; Drive -- current drive
;
; FLAG LOCATIONS:
;
; 103H -- Change to non-zero value to suppress
; translation of several non-standard opcodes:
; REQ, RNE, RLT, RGE, CEQ, CNE, CLT, CGE
; JEQ, JNE, JLT, JGE,
; ENT, NAM, RAM, ROG, IFC, ICL, LST, MAC
;
; 104H -- If non-zero (default) XLT86 converts lines
; with multiple statements separated by DR's EP
; separator into separate lines.
; Change to zero for output on a single line
; with the translated statements separated by
; EP.
;
; 107H-- If zero (default) XLT86 translates
;
; PUSH PSW POP PSW
;
; to
;
; LAHF POP AX
; PUSH AX SAHF
;
; Otherwise, the translation is
;
; LAHF POP AX
; XCHG AH,AL XCHG AH,AL
; PUSH AX SAHF
; XCHG AH,AL
;
; 108H-- If zero (default) XLT86 translates
;
; INX rp DCX rp
;
; to
;
; INC rp' DEC rp'
;
; Otherwise, the translation is
;
; PUSHF PUSHF
; INC rp' DEC rp'
; POPF POPF
;
; 109H-- If zero (default) XLT86 translates
;
; DAD rp
;
; to
;
; ADD BX,rp'
;
; Otherwise, the translation is
;
; PUSHF
; ADD BX,rp'
; POPF
;
N00 EQU 0
N01 EQU 1
;
N07 EQU 7
N09 EQU 9 ;tab every 8th col.
NF8 EQU 0F8H ;mod 8
;
LBUFLN EQU 80 ;line buffer length
OPBFLN EQU 5 ;opcode buffer length
MEMSIZ EQU 4 ;memory available in Kb
IBNUM EQU 4*MEMSIZ
OBNUM EQU 4*MEMSIZ
RECLEN EQU 128 ;
STCKLN EQU 128 ;stack size
IBFLEN EQU IBNUM*RECLEN
OBFLEN EQU OBNUM*RECLEN
;
CTRLC EQU 3
EOT EQU 4
BEL EQU 7
HT EQU 9
LF EQU 0AH
CR EQU 0DH
ESC EQU 1BH
QUOTE EQU 27H
;
ABORT EQU 0000
BDOS EQU 0005
DFCB1 EQU 005CH
DFCB2 EQU 006CH
;
FNLEN EQU 8
EOS EQU EOT ; replacement for exclamation pt
EOF EQU 1AH
NFF EQU 0FFH ;disk error return
;
; BDOS FUNCTIONS
;
nCIN EQU 1
nCOUT EQU 2
nCDAV EQU 0BH
nOPEN EQU 0FH
nCLOSE EQU 10H
nDEL EQU 13H
nRDNR EQU 14H
nWRNR EQU 15H
nCREAT EQU 16H
nCDISK EQU 19H
nDMA EQU 1AH
;
;
ORG 100H
;
JMP START
;
; OPTION FLAGS
;
PSEFLG DB 0 ;(103H) 0 to translate non-
; standard opcodes
MLTLFL DB 0FFH ;(104H) 0 to put input line with
; exc. pt. to output on one line
TCASFL DB 0 ;(105H) 0 to preserve case
;
LCASFL DB 0 ;(106H) 0 for upper case if
; TCASFL not zero
PSWFL DB 0 ;(107H) non-zero to preserve 8080
; order of PSW registers on stack
INXFL DB 0 ;(108H) non-zero to preserve flags
; with INX and DCX translations
DADFL DB 0 ;(109H) non-zero to preserve flags
; with DAD translation
;
; HELP MESSAGE
;
HMSG1:
DB CR,LF
DB LF
DB 'XLT86 translates Intel 8080 assembly language source',CR,LF
DB 'code into Intel 8086 assembly language source code.',CR,LF
DB LF
DB 'It is invoked by a command of the form:',CR,LF
DB LF
DB ' XLT86 [d:]srcfile[.typ] [d:destfile.typ]',CR,LF
DB LF
DB 'The brackets denote optional parameters and the ',CR,LF
DB 'default values are:',CR,LF
DB LF
DB ' Source file-type -- ASM',CR,LF
DB ' Destination file-type -- A86',CR,LF
DB ' Destination file-name -- same as source file-name',CR,LF
DB ' Drive -- current drive',CR,LF
DB CR,LF
DB 'Press any key to continue - ',0
HMSG2:
DB CR,LF
DB LF
DB 'Examples:',CR,LF
DB LF
DB 'XLT86 PRGM1 --translates PRGM1.ASM to PRGM1.A86',CR,LF
DB 'XLT86 PRGM1 PRGM2 --translates PRGM1.ASM to PRGM2.A86',CR,LF
DB 'XLT86 PRGM1.TXT PRGM2.MAC --translates PRGM1.TXT to PRGM2.MAC',CR,LF
DB LF
DB 'XLT86 also has the following features:',CR,LF
DB LF
DB 'Case will be preserved as well as possible -- if an opcode has',CR,LF
DB 'a lower case character, the translated opcode will be in lower',CR,LF
DB 'case.',CR,LF
DB LF
DB 'All asterisks at the beginning of lines will be replaced with',CR,LF
DB 'semicolons.',CR,LF
DB LF
DB 'A dot is printed on the console for every 100 lines of input ',CR,LF
DB 'processed.',CR,LF
DB LF
DB 0
;
;=============================================================================
;
; Program begins here
;
START:
LXI H,0
DAD SP
SHLD SPBDOS
LXI SP,STACK
LDA DFCB1+1 ; check for a file name
CPI ' ' ; print help if no name
JNZ BEGIN ; no help requested
LXI D,SIGNON
CALL PRTLIN
LXI D,HMSG1 ; print help message
CALL PRTLIN
MVI C,nCIN ; wait for any character
CALL BDOS
LXI D,HMSG2 ; print rest of help
CALL PRTLIN
LHLD SPBDOS ; retrieve system stack
SPHL ; pointer and pop
RET ; to PC
BEGIN: CALL HELLO ;signon, open in & out files
NXTLIN: CALL GETLIN ;get line from input file to buf
CALL PROCLIN ; process line
JMP NXTLIN
;
;
;
;*******************************************************
;
; Print signon, open input
; and output files.
;
HELLO: LXI D,SIGNON
CALL PRTLIN
HELLO0: MVI A,'D' ; translate DB & EQU (for
STA OPTBDB ; uniform formatting)
MVI A,HT ; Default is tab after opcode
STA MLTSPC ; for stmts on separate lines
MVI A,HT ; HT after opcode
STA PUTHT+1
MVI A,41 ; tab comments to col 33
STA PUTND5+1
MVI A,0FEH ; CP instruction
STA EXCLAM
XRA A
STA TCASFL ; don't convert case
STA LCASFL ; lower case flag
LXI H,NEWLSP
SHLD SEPMSG
LDA PSEFLG ; translate non-standard
ORA A ; opcodes ?
CNZ NXPSD
LXI D,DBMSG
CALL PRTLIN ;
CALL CHKYES ; xlat DB & EQU ?
CPI ESC
JZ HELLO0
CPI CTRLC
JZ ABORT
CPI 'Y'
CNZ NXDBEQ
LDA MLTLFL ; force space after opcode
ORA A ; if MLTLFL not set
JZ HELLO2
LXI D,SPCMSG
CALL PRTLIN ; use space after
CALL CHKYES ; opcode ?
CPI ESC
JZ HELLO0
CPI CTRLC
JZ ABORT
CPI 'Y'
HELLO2: CZ SETSPC
LXI D,COLMSG
CALL PRTLIN ;
CALL CHKYES ; start comment
CPI ESC
JZ HELLO0
CPI CTRLC
JZ ABORT
CPI 'Y'
CZ SETCOL ; in column 25 ?
LXI D,EXCMSG
CALL PRTLIN ; Ignore exclamation point
CALL CHKYES ; separator ?
CPI ESC
JZ HELLO0
CPI CTRLC
JZ ABORT
CPI 'Y'
CZ SETNEX
LXI D,MLTMSG
CALL PRTLIN ; multiple statements
CALL CHKYES ; on one line ?
CPI ESC
JZ HELLO0
CPI CTRLC
JZ ABORT
CPI 'Y'
CZ SETMLT
LXI D,TRNMSG ; Convert case ?
CALL PRTLIN
CALL CHKYES
CPI ESC
JZ HELLO0
CPI CTRLC
JZ ABORT
CPI 'L'
CZ SETLC
CPI 'U'
CZ SETUC
MVI A,N01
STA COLNUM
MVI C,nCDISK
CALL BDOS
INR A
STA xCDISK
CALL MAKFNS
CALL OPENIN
CALL CREATO
RET
;
SIGNON DB '8080-to-8086 Translator version '
DB VERS/100+'0','.',(VERS MOD 100)/10+'0'
DB (VERS MOD 10)+'0'
DB CR,LF,0
;
; Don't translate non-standard opcodes
;
NXPSD: XRA A
STA OPTTDL
STA OPTENT
STA OPTIFC
RET
DBMSG DB 'Translate DB & EQU ? '
DB '[Y/ret=N/esc/^C] ',0
;
NXDBEQ: XRA A
STA OPTBDB
RET
;
SPCMSG DB 'Use space (default TAB) after opcode ? '
DB '[Y/ret=N/esc/^C] ',0
;
SETSPC: LXI H,PUTHT+1
MVI A,' '
MOV M,A
STA MLTSPC
RET
;
COLMSG DB 'Start comment in column 25 (default 33) ? '
DB '[Y/ret=N/esc/^C] ',0
;
SETCOL: LXI H,PUTND5+1
MVI A,33
MOV M,A
RET
;
EXCMSG DB 'Ignore ! statement separator ? '
DB '[Y/ret=N/esc/^C] ',0
;
SETNEX: MVI A,0C9H ; RET instruction
STA EXCLAM
RET
;
MLTMSG DB 'Put opcodes converted to multiple'
DB ' statements on one line ? '
DB '[Y/ret=N/esc/^C] ',0
;
SETMLT: LXI H,EXCLSP
SHLD SEPMSG
MVI A,' '
STA MLTSPC
RET
;
TRNMSG DB 'Translate instructions to Upper/Lower'
DB ' or preserve case ? [U/L/ret/esc/^C] ',0
;
SETLC: STA TCASFL
STA LCASFL
RET
;
SETUC: STA TCASFL
RET
;*******************************************************
;
; Gets line from input file to line
; buffer until CR. Filters out ctrl
; chars except for HT. Truncates
; lines after LBUFLN chars.
; Terminates line with CR, LF, 0.
;
GETLIN: CALL PDOT ; print activity dot
CALL CHKIN
CPI CTRLC
JZ JABORT
XRA A
STA QUOTFL ; not in quote
STA CMNTFL ; not in comment
LXI H,LBUFF ;line buffer
MVI B,LBUFLN ;max # of char
GETLN1: XCHG
LHLD xIBUFF
XCHG
MOV A,D
CPI (IBUFF+IBFLEN)/256
JNZ GETLN4
MOV A,E
CPI (IBUFF+IBFLEN) MOD 256
JNZ GETLN4
PUSH B
PUSH H
LXI D,IBUFF
GETLN2: MVI C,nDMA
PUSH D
CALL BDOS
POP D
XCHG
LXI D,INFCB
MVI C,nRDNR
PUSH H
CALL BDOS
POP H
DCR A
JNZ GETLN3
MVI A,EOF
MOV M,A
GETLN3: LXI D,RECLEN
DAD D
XCHG
MOV A,D
CPI (IBUFF+IBFLEN)/256
JNZ GETLN2
MOV A,E
CPI (IBUFF+IBFLEN) MOD 256
JNZ GETLN2
POP H
POP B
LXI D,IBUFF
GETLN4: LDAX D
INX D
XCHG
SHLD xIBUFF
XCHG
MOV M,A
CPI QUOTE ; set or reset
JNZ GTLN41 ; QUOTFL
LDA QUOTFL
CMA
STA QUOTFL
GTLN41: MOV A,M ; Translate exclam. pt.
CALL EXCLAM ; which is not in quote
MOV M,A ; to EOS
LDA TCASFL ; translate to upper
ORA A ; or lower case ?
JZ GTLN46 ; NO
LDA QUOTFL ; if in quote, do
ORA A ; nothing
JNZ GTLN43
MOV A,M ; otherwise, ';' sets
CPI ';' ; CMNTFL and EOS resets
JZ GTLN42 ; it
CPI EOS
JNZ GTLN43
XRA A
GTLN42: STA CMNTFL
GTLN43: LDA QUOTFL ; If in quote,
ORA A ; do nothing
JNZ GTLN46
LDA CMNTFL ; If in comment,
ORA A ; do nothing
JNZ GTLN46
LDA LCASFL ; Otherwise,
ORA A ; if LCASFL set
MOV A,M
JZ GTLN44
CALL LCASE ; trns to lwr case
JMP GTLN45
GTLN44: CALL UCASE ; else trns to upr case
GTLN45: MOV M,A
GTLN46: MOV A,M
CPI CR
JZ GETLN6
CPI HT ; filters out all ctrl
JZ GETLN5 ; chars except tab
CPI EOF
JZ GETLN7
CPI EOS
JZ GETLN5
CPI ' '
JC GETLN1
GETLN5: DCR B
INX H
JNZ GETLN1
INR B
DCX H
JMP GETLN1
;
GETLN6: INX H
MVI M,LF
INX H
MVI M,N00
XCHG
SHLD xIBUFF
XCHG
RET
;
; Change exclamation point to EOS in A
;
EXCLAM: CPI '!'
RNZ
LDA QUOTFL
ORA A
MVI A,'!'
RNZ
MVI A,EOS
RET
;
QUOTFL DB 0
CMNTFL DB 0
;
; Exit
;
GETLN7: CALL CLOSEO
LXI D,UPSMSG
CALL PRTLIN
LXI D,ENDIFL
CALL PRTLIN
LXI D,ICLFLG
CALL PRTLIN
LXI D,LSTFLG
CALL PRTLIN
LXI D,MACFLG
CALL PRTLIN
LXI D,EOJMSG
;
; Print message at DE and abort
;
EREXIT: PUSH D
LXI D,CRLFMG
CALL PRTLIN
POP D
CALL PRTLIN
JMP ABORT
;
JABORT: LXI D,JABTMG
CALL PRTLIN
JMP GETLN7
;
JABTMG DB CR,LF,'*** Job Cancelled ***',CR,LF,0
;
UPSMSG DB 0,LF,'The following operands'
DB ' have been used in your '
DB 'source and have not'
DB CR,LF
DB 'been fully translated. You must '
DB 'complete the translation using an editor.'
DB CR,LF,HT
DB 'original:',HT,HT
DB 'must be translated to:'
DB CR,LF,0
ENDIFL DB 0,'IF or IFC',HT,HT,'%IF(exp)THEN(txt1)',CR,LF
DB HT,'ELSE',HT,HT,HT,'ELSE(txt2)',CR,LF
DB HT,'ENDIF or #ENDIF',HT,HT,'FI'
DB CR,LF,0
ICLFLG DB 0,'ICL'
DB CR,LF,0
LSTFLG DB 0,'LST or LIST'
DB CR,LF,0
MACFLG DB 0,'MACRO or MAC',HT,HT,'%DEFINE(mname[(plist)])'
DB CR,LF
DB HT,'#macro-call',HT,HT,'%macro-call'
DB CR,LF,0
;
EOJMSG DB '*** End of Job ***',CR,LF,0
;*******************************************************
;
; Process line
;
PROCLIN:
LXI H,LBUFF
PROCLN0:
CALL FNDOPC
JNZ PRCLN00
CALL PTCOLN ; Put out pending colon
JMP PUTND6
PRCLN00:
LDA COLNFL ; is there a colon
ORA A ; to print ?
JZ PRCLN02 ; No, put white space
LXI H,OPTPSD ; See if opcode
LXI B,OPBFLN ; is DB, DW, DS, or EQU
CALL SCANOP
MVI A,' '
JZ PRCLN01 ; If so, put space
MVI A,':' ; otherwise, put colon
PRCLN01:
CALL PUTCHR
PRCLN02:
LHLD xWHITE
CALL PUTSPT
PROCLN1:
LXI H,OPTIMM ;imm or one byte
LXI B,2*OPBFLN
CALL SCANOP
JZ DOIMM
LXI H,OPTONE ; one byte opcodes
LXI B,2*OPBFLN
CALL SCANOP
JZ DO$ONE
LXI H,OPTREG ;register
LXI B,2*OPBFLN
CALL SCANOP
JZ DOREG
LXI H,OPTBDB ; db and equ
LXI B,2*OPBFLN
CALL SCANOP
JZ DOSIMP
LXI H,OPTSMP ; simple
LXI B,2*OPBFLN
CALL SCANOP
JZ DOSIMP
LXI H,OPTROT ; rotates
LXI B,2*OPBFLN
CALL SCANOP
JZ DOROT
LXI H,OPTDCR ; dcr, inr
LXI B,2*OPBFLN
CALL SCANOP
JZ DODCR
LXI H,OPTDCX ;16 bit dcx, inx
LXI B,2*OPBFLN
CALL SCANOP
JZ DODCX
LXI H,OPTTDL ;tdl
LXI B,OPBFLN
CALL SCANOP
CZ DOTDL
LXI H,OPTRCC ;ret cond
LXI B,2*OPBFLN
CALL SCANOP
JZ DORET
LXI H,OPTCCC ;call cond
LXI B,2*OPBFLN
CALL SCANOP
JZ DOCALL
LXI H,OPTJCC ;jump cond
LXI B,2*OPBFLN
CALL SCANOP
JZ DOJMP
LXI H,OPTMSC ;index & misc
LXI B,2*OPBFLN+2
CALL SCANOP
JZ EXEC
PUTCOD: LHLD xOPCOD ;this fix prevents macro
JMP PUTEND ;names from being split
PUTOPR: LHLD xOPRND
PUTEND: XRA A
STA LCFLAG
STA LCDFLG
MVI C,N00 ; putout w/o
PUTND1: MOV A,M ; change
CPI ' '
JZ PUTND3
CPI HT
JZ PUTND3
CPI CR
JZ PUTLNC
CPI ';'
JZ PUTND4
CPI EOS ; process exclamation pt.
JZ PTND21 ; statement separator
CPI QUOTE
JNZ PUTND2
DCR C
JZ PUTND2
MVI C,N01
PUTND2: CALL PUTCHR
INX H
JMP PUTND1
;
PTND21: CALL SKSPHT
INX H ; Inc past excl. pt.
PTND22: MOV A,M
CPI ';'
JZ PUTND5
LDA MLTLFL ; Put out as separate
ORA A ; lines
JZ PTND24 ; NO
;
MOV A,M
CPI ' ' ; Change space to HT
JNZ PTND23
MVI M,HT
PTND23: CALL PCRLF
JMP PROCLN0
;
PTND24: LDA TEMP ; Was last character put
CPI ' ' ; out a space ?
JZ PTND25
CPI HT ; or a TAB ?
JZ PTND25
MVI A,' ' ; NO, put out a space
CALL PUTCHR
PTND25: MVI A,'!'
CALL PUTCHR
JMP PROCLN0
;
;
PUTND3: PUSH H ;Space or Tab come here
CALL SKSPHT
CPI CR ;this fix filters out
JZ PUTLNB ;trailing spaces or tabs
POP H
CPI EOS ; fix to process excl. pt.
JZ PTND21
CPI ';'
MOV A,M ;prevent blank being replaced
;by ';' in string data
JZ PUTND4
CALL PUTSPT
JMP PUTND1
;
PUTND4: DCR C ;';' come here
INR C
JNZ PUTND2
CALL SKSPHT
; Tab comments to proper column
PUTND5: MVI B,41
PTND51: LDA COLNUM
CMP B ;colnum>=41?
JNC PTND54
DCR A ;no, insert
ANI NF8 ;tabs to
ADI N09 ;start output
CMP B ;at col. 33
JZ PTND54
JC PTND52
MVI A,' '
JMP PTND53
;
PTND52: MVI A,HT
PTND53: CALL PUTCHR
JMP PTND51
PTND54: LDA TEMP ; insure
CPI ' ' ; space
JZ PUTND6 ; before
CPI HT ; semi-colon
JZ PUTND6 ;
MVI A,' ' ;
CALL PUTCHR ;
PUTND6: MOV A,M
INX H
CPI EOS
JZ PTND22
ORA A
RZ
CALL PUTCHR
JMP PUTND6
;
; Put line at HL to output file until 0
; and reset colnum to 1.
;
PUTLNB: XTHL ;filter trailing
POP H ;blanks or tabs
PUTLNC: JMP PUTLIN
;*******************************************************
;
; Process labels, find potential opcode.
;
FNDOPC: XRA A
STA COLNFL ; Reset colon flag
MOV A,M
CPI ' '
JZ FNDOP3
CPI HT
JZ FNDOP3
CPI CR ;pass blank
RZ ;lines
CPI EOS ; excl. pt. separator
RZ
CPI ';'
RZ
CPI '*' ; asterisk in first column
JNZ FNDOP1 ; is a comment line
MVI M,';'
RET
;
; Only comes here if this is a label
;
FNDOP1: MVI C,N00
MVI A,':' ; Set colon flag
STA COLNFL ; to insure colon after label
FNDOP2: MOV A,M
CPI ':'
JZ FNDOP4
CPI HT
JZ FNDOP6
CPI ' '
JZ FNDOP6
CPI CR
RZ
CPI EOS
RZ
CPI ';'
JZ FNDP72
CALL PUTCHR
INX H
INR C
JMP FNDOP2
; Comes here only if space or tab at beginning
; of line.
FNDOP3:
PUSH H
CALL SKSPHT ;find first non-sp or tab
CPI CR
JZ FNDOP9
CPI EOS
JZ FNDOP9
CPI ';'
JZ FNDP71
POP H
CALL PUTSPT ;print until non-sp or ht
PUSH H
CALL FINDLM ;find ,:+-/*); CR HT or SP at HL
CPI ':'
POP H
JZ FNDOP1
JMP FNDOP7
;
; Colon terminating label comes here
;
FNDOP4: INX H
MOV A,M
CPI ':'
JNZ FNDOP5
CALL PUTCHR
INX H
FNDOP5: MVI A,':'
STA COLNFL ; Set colon flag
;
; HT or SP comes here
;
FNDOP6:
;
; See if there is an opcode field
;
FNDOP7: PUSH H
CALL SKSPHT
MOV A,M
CPI CR
JZ FNDOP9 ; filter trailing SP or TAB
CPI EOS
JZ FNDOP9 ; excl. pt. separator
CPI ';'
JNZ FNDOP8
FNDP71: XTHL
POP H
FNDP72: POP B ; clear return
CALL PTCOLN ; Put colon out if flag set
JMP PUTND5 ; tab to proper column
;
; Have located opcode field
;
FNDOP8: POP H
SHLD xWHITE
CALL SKSPHT
; Move potential opcode to OPCBUF
MOVOPC: SHLD xOPCOD
MVI B,OPBFLN
LXI D,OPCBUF
CALL MOVBDH ; move up to B char from HL to
CALL SKSPHT ; DE until ,:+-/*); CR HT SP
SHLD xOPRND
SUB A
INR A
RET
; come here on CR to filter trailing SP or TAB
FNDOP9: CALL PTCOLN ; Put out colon if flag set
XTHL
POP H
XRA A
RET
;
; Put colon to output file if colon
; flag is set.
;
PTCOLN: LDA COLNFL
ORA A
RZ
CALL PUTCHR
XRA A
STA COLNFL
RET
;
COLNFL DB 0
xWHITE DW 0 ; pointer to white space after
; label and before opcode
;*******************************************************
;
; Opcode tables
;
OPTIMM DB 'ACI ADC '
DB 'ADI ADD '
DB 'ANI AND '
DB 'CPI CMP '
DB 'ORI OR '
DB 'SBI SBB '
DB 'SUI SUB '
DB 'XRI XOR '
DB 0
OPTONE DB 'RET RET '
DB 'CMC CMC '
DB 'HLT HLT '
DB 'STC STC '
DB 'DAA DAA '
DB 'DI CLI '
DB 'EI STI '
DB 'NOP NOP '
DB 0
OPTREG DB 'ADC ADC '
DB 'ADD ADD '
DB 'ANA AND '
DB 'CMP CMP '
DB 'ORA OR '
DB 'SBB SBB '
DB 'SUB SUB '
DB 'XRA XOR '
DB 0
OPTPSD DB 'DB '
DB 'EQU '
DB 'DW '
DB 'DS '
DB 0
OPTBDB DB 'DB DB '
DB 'EQU EQU '
DB 0
OPTSMP DB 'JMP JMP '
DB 'CALL CALL '
DB 'DS RS '
DB 'DW DW '
DB 'SET EQU '
OPTENT DB 'ENT ENTRY'
DB 'NAM NAME '
DB 'RAM DATA '
DB 'ROG REL '
DB 0
OPTDCR DB 'DCR DEC '
DB 'INR INC '
DB 0
OPTROT DB 'RAL RCL '
DB 'RAR RCR '
DB 'RLC ROL '
DB 'RRC ROR '
DB 0
OPTDCX DB 'DCX DEC '
DB 'INX INC '
DB 0
OPTTDL DB 'REQ '
DB 'RNE '
DB 'RLT '
DB 'RGE '
DB 'CEQ '
DB 'CNE '
DB 'CLT '
DB 'CGE '
DB 'JEQ '
DB 'JNE '
DB 'JLT '
DB 'JGE '
DB 0
OPTRCC DB 'RC JNC '
DB 'RNC JC '
DB 'RZ JNZ '
DB 'RNZ JZ '
DB 'RP JS '
DB 'RM JNS '
DB 'RPE JPO '
DB 'RPO JPE '
DB 0
OPTCCC DB 'CC JNC '
DB 'CNC JC '
DB 'CZ JNZ '
DB 'CNZ JZ '
DB 'CP JS '
DB 'CM JNS '
DB 'CPE JPO '
DB 'CPO JPE '
DB 0
OPTJCC DB 'JC JNC '
DB 'JNC JC '
DB 'JZ JNZ '
DB 'JNZ JZ '
DB 'JP JS '
DB 'JM JNS '
DB 'JPE JPO '
DB 'JPO JPE '
DB 0
OPTMSC DB 'LXI MOV '
DW DOLXI
DB 'POP POP '
DW DOPOP
DB 'PUSH PUSH '
DW DOPSH
DB 'DAD ADD '
DW DODAD
DB 'LDA MOV '
DW DOLDA
DB 'LDAX MOV '
DW DOLDAX
DB 'LHLD MOV '
DW DOLHLD
DB 'MOV MOV '
DW DOMOV
DB 'MVI MOV '
DW DOMVI
DB 'IN IN '
DW DOIN
DB 'OUT OUT '
DW DOOUT
DB 'PCHL JMP '
DW DOPCHL
DB 'RST CALL '
DW DORST
DB 'SHLD MOV '
DW DOSHLD
DB 'SPHL MOV '
DW DOSPHL
DB 'STA MOV '
DW DOSTA
DB 'STAX MOV '
DW DOSTAX
DB 'XCHG XCHG '
DW DOXCHG
DB 'XTHL XCHG '
DW DOXTHL
DB 'CMA NOT '
DW DOCMA
DB 'IF IF '
DW DOIFC
DB 'LIST LIST '
DW DOLST
DB 'MACROMACRO'
DW DOMAC
OPTIFC DB 'IFC IF '
DW DOIFC
DB 'ICL *INCL'
DW DOICL
DB 'LST LIST '
DW DOLST
DB 'MAC MACRO'
DW DOMAC
DB 0
;*******************************************************
;
; Scan table at HL for match to OPBFLN
; char string at OPCBUF.
; Ret Z and HL-> entry if match.
;
SCANOP: MOV A,M
ANA A
JZ SCNOP1
PUSH B
MVI B,OPBFLN
LXI D,OPCBUF
CALL CBDEHL ;comp B bytes (DE)-(HL)
POP B
RZ
DAD B
JMP SCANOP
;
SCNOP1: INR A
RET
;
; Gets routine address from
; HL+2*OPBFLN and jumps to routine.
;
EXEC: PUSH H
LXI B,2*OPBFLN
DAD B
MOV C,M
INX H
MOV B,M
POP H
PUSH B ;address on stack
RET ;go to it
;
; Put up to OPBFLN char at HL+OPBFLN
; to output file. Stop at space,
; and put tab to output file.
;
PUTOPHT:
CALL PUTOPC
PUTHT: MVI A,HT
JMP PUTCHR
;
; Put space or tab (contents of MLTSPC)
; to output file as separator after opcode
; in multi-statement output line.
;
PUTHTS: LDA MLTSPC
JMP PUTCHR
;
MLTSPC DB HT
;
;
;
PUTOPC: LXI B,OPBFLN
DAD B ; HL -> new opcode
MOV B,C
PUTOP1: MOV A,M
CPI ' '
RZ
CPI HT
RZ
LDA LCFLAG
ORA A
MOV A,M
JZ PUTOP2
ORI 20H
PUTOP2:
CALL PUTCHR
INX H
DCR B
JNZ PUTOP1
RET
;
; Put string at HL to output file until 0.
; If (LCFLAG) set, convert to lower case.
;
PUTOPS: MOV A,M
ORA A
RZ
LDA LCFLAG
ORA A
MOV A,M
JZ PUTOS0
CALL LCASE
PUTOS0: CALL PUTCHR
INX H
JMP PUTOPS
;
; Put string at HL to output file until 0.
; If (LCDFLG) set, convert to lower case.
;
PUTRND: MOV A,M
ORA A
RZ
LDA LCDFLG
ORA A
MOV A,M
JZ PUTRN0
CALL LCASE
PUTRN0: CALL PUTCHR
INX H
JMP PUTRND
;
LCDFLG DB 0
;
; Find first ,:+-/*); CR HT or SP at HL,
; return A = (HL).
;
FINDLM: PUSH B
CALL CHKDLM
POP B
RZ
INX H
JMP FINDLM
;
; Fill B locations at DE with spaces.
; Move up to B char from HL to DE until
; ,:+-/*); CR HT or SP encountered.
; Return Z and HL->special char if found.
; (search B+1 loc for special char.)
;
MOVBDH: MOV C,B
MVI B,N00
PUSH B
PUSH D
PUSH H ; fill BC locations
CALL FILLBD ; at DE with spaces
POP H ;
POP D
POP B
MOVBD1: PUSH B ; ret Z, A=(HL)
CALL CHKDLM ; if (HL) is
POP B ; ,:+-/*); CR HT or SP
RZ
MOV A,M
STAX D
INX D
INX H
DCX B
MOV A,B
ORA C
JZ CHKDLM
JMP MOVBD1
;
; Skip spaces and tabs.
; Return HL -> non-space or non-tab
;
SKSPHT: MOV A,M
CPI ' '
JZ SKSPT1
CPI HT
RNZ
SKSPT1: INX H
JMP SKSPHT
;
; Ret Z, A=(HL) if
; HL is ,:+-/*); CR HT SP or EOS
;
CHKDLM: MOV A,M
CPI HT
RZ
CPI ' '
RZ
CPI ','
RZ
CPI ';'
RZ
CPI CR
RZ
CPI ':'
RZ
CPI '+'
RZ
CPI '-'
RZ
CPI '/'
RZ
CPI '*'
RZ
CPI ')'
RZ
CPI EOS
RET
;
; Compares B chars at DE with chars
; at HL.
; Ret Z if match.
; Preserve HL, DE, BC
;
CBDEHL: PUSH H
PUSH D
PUSH B
CBDH1: LDAX D
CPI 'a'
JC CBDH2
STA LCFLAG
ANI 05FH
CBDH2:
CMP M
JNZ CBDH3
INX H
INX D
DCR B
JNZ CBDH1
CBDH3: POP B
POP D
POP H
RET
LCFLAG DB 0
;
; Fill BC locations starting at
; DE with spaces.
; Returns A = space, DE -> next free
; location, HL = DE - 1, BC = 0.
;
FILLBD: MVI A,' '
STAX D
MOV H,D
MOV L,E
INX D
DCX B
CALL MOVIR
RET
;
; Subtract DE from HL, result in HL.
;
SBCHLDE:
MOV A,L
SUB E
MOV L,A
MOV A,H
SBB D
MOV H,A
RET
;
; (DE)=(HL), INC HL, INC DE, DEC BC
; Repeat until BC = 0.
;
MOVIR: MOV A,M
STAX D
INX H
INX D
DCX B
MOV A,B
ORA C
JNZ MOVIR
RET
;*******************************************************
;
; Translation Routines
;
;*******************************************************
;
; Immediate
; e.g., CPI n -> CMP AL,n
;
DOIMM: CALL PUTOPHT
LXI H,OPALC
CALL PUTOPS
JMP PUTOPR
;
OPALC DB 'AL,',0
;
; One byte (implied)
; e.g., DI -> CLI
;
DO$ONE: CALL PUTOPC
JMP PUTOPR
;
; Simple translation
; e.g., DS n -> RS n
;
DOSIMP: CALL PUTOPHT
JMP PUTOPR
;
; Register instructions,
; e.g., XRA r -> XOR AL,r'
;
DOREG: CALL PUTOPHT ; Put out opcode+tab
LXI H,OPALC ; Put out 'AL,'
CALL PUTOPS
LHLD xOPRND
CALL TRNRG ; Translate register
JNZ PUTEND
XCHG ; Get HL -> r'
CALL PUTRND
XCHG
JMP PUTEND
;
; MOV r,s -> MOV r',s'
;
DOMOV: CALL PUTOPHT
LHLD xOPRND
CALL TRNRG
JNZ PUTOPR
XCHG
CALL PUTRND
XCHG
XRA A
STA LCDFLG ; Clear lower case flag
MOV A,M ; Get comma
INX H ; Inc past ','
CALL PUTCHR
CALL TRNRG
JNZ PUTEND
XCHG
CALL PUTRND
XCHG
JMP PUTEND
;
; Dec and Inc byte register
; DCR r -> DEC r'
;
DODCR:
;
; MVI r,n -> MOV r',n
;
DOMVI: CALL PUTOPHT
LHLD xOPRND
CALL TRNRG
JNZ PUTEND
LDAX D
CPI '['
JNZ DOMVI1
PUSH H
LXI H,OPBYTP
CALL PUTLIN
POP H
DOMVI1: XCHG
CALL PUTRND
XCHG
JMP PUTEND
;
OPBYTP DB 'BYTE PTR ',0
;
; Translate 8080 byte registers to
; 8086 byte registers.
; Enter with HL -> to 8080 register.
; If match,
; return Z set, HL -> next, DE -> translation,
; Otherwise,
; return NZ, HL, DE unchanged.
;
TRNRG: MOV A,M
CPI 'a'
JC TRNRG2
STA LCDFLG
TRNRG2: ANI 5FH
PUSH H
LXI H,RTBL
MVI B,RTBLE-RTBL
TRNRG3: CMP M
JZ TRNRG4
INX H
DCR B
JNZ TRNRG3
POP H ; HL -> r
MVI A,0FFH ; return NZ
ORA A ; if no match
RET
;
TRNRG4: LXI D,RTBL
CALL SBCHLDE
DAD H
LXI D,RPTBL
DAD D
MOV E,M
INX H
MOV D,M
POP H
INX H ; point to next
XRA A ; return Z
RET
;
RTBL DB 'ABCDEHLM'
RTBLE:
RPTBL DW ALREG
DW CHREG
DW CLREG
DW DHREG
DW DLREG
DW BHREG
DW BLREG
DW PBX
;
ALREG DB 'AL',0
CHREG DB 'CH',0
CLREG DB 'CL',0
DHREG DB 'DH',0
DLREG DB 'DL',0
BHREG DB 'BH',0
BLREG DB 'BL',0
PBX DB '[BX]',0
;
; Rotates
;
DOROT: CALL PUTOPHT
LXI H,OPALC ; 'AL,'
CALL PUTOPS
MVI A,'1'
CALL PUTCHR
JMP PUTOPR
;
; DAD rp -> ADD BX,rp'
;
DODAD: LDA DADFL
ORA A
JZ DODAD1
PUSH H
LXI H,OPPSHF ;'PUSHF'
CALL PUTOPS
CALL SEP ; separator
POP H
CALL PUTOPC
CALL PUTHTS ; Put out space or tab
JMP DODAD2
DODAD1: CALL PUTOPHT
DODAD2: LXI H,OPBXC ;'BX,'
CALL PUTOPS
LHLD xOPRND
CALL TRNRP ; DE -> translated rp
JNZ PUTOPR
LDAX D
CPI 'A'
JZ PUTOPR
XCHG ; HL -> translated rp
CALL PUTRND
XCHG ; HL -> next
LDA DADFL
ORA A
JZ PUTEND
PUSH H
CALL SEP ; Separator
LXI H,OPPOPF ; 'POPF'
CALL PUTOPS
POP H
JMP PUTEND
;
OPBXC DB 'BX,',0
;
; DCX or INX rp -> DEC or INC rp'
;
DODCX: LDA INXFL ; If set, output
ORA A ; PUSHF to preserve
JZ DODCX1 ; flags
PUSH H
LXI H,OPPSHF ;'PUSHF'
CALL PUTOPS
CALL SEP ; separator
POP H
CALL PUTOPC
CALL PUTHTS ; Put out space or tab
JMP DODCX2
DODCX1: CALL PUTOPHT
DODCX2: LHLD xOPRND
CALL TRNRP ; DE -> translated rp
JNZ PUTOPR
LDAX D
CPI 'A'
JZ PUTOPR
XCHG ; HL -> translated rp
CALL PUTRND
XCHG ; HL -> next
LDA INXFL ; If set, output
ORA A ; POPF to preserve
JZ PUTEND ; flags
PUSH H
CALL SEP ; Separator
LXI H,OPPOPF ; 'POPF'
CALL PUTOPS
POP H
JMP PUTEND
;
OPPSHF DB 'PUSHF',0
OPPOPF DB 'POPF',0
;
; PUSH rp -> PUSH rp'
;
DOPSH: XCHG
LHLD xOPRND
MOV A,M
ANI 5FH
CPI 'P'
XCHG
JNZ DOPSH1
XCHG
CALL TRNRP ; DE -> trans, HL -> next
JNZ PUTCOD
PUSH H
LXI H,OPLAHF
CALL PUTRND
LDA PSWFL ; Preserve order of
ORA A ; registers on stack ?
CNZ XAHAL ; Yes, XCHG AH,AL
CALL SEP ; SP,EP,SP or CR, LF, HT
LXI H,OPPUSH
CALL PUTOPS
CALL PUTHTS
POP H
XCHG ; HL -> translated rp
CALL PUTRND
XCHG ; HL -> next
LDA PSWFL
ORA A
CNZ XAHAL
JMP PUTEND
;
DOPSH1: CALL PUTOPHT
DOPSH2: LHLD xOPRND
CALL TRNRP ; DE -> translated rp
JNZ PUTOPR
DOPSH3: XCHG ; HL -> translated rp
CALL PUTRND
XCHG ; HL -> next
JMP PUTEND
;
OPLAHF DB 'LAHF',0
OPPUSH DB 'PUSH',0
;
XAHAL: PUSH H
CALL SEP
LXI H,OPXCHG
CALL PUTRND
CALL PUTHTS
LXI H,OPAHAL
CALL PUTRND
POP H
RET
;
OPXCHG DB 'XCHG',0
OPAHAL DB 'AH,AL',0
;
; POP rp -> POP rp'
;
DOPOP: XCHG
LHLD xOPRND
MOV A,M
ANI 5FH
CPI 'P'
XCHG
JNZ DOPSH1
CALL PUTOPC
CALL PUTHT ; Put out space or tab
LHLD xOPRND
CALL TRNRP ; DE -> trans, HL -> next
JNZ PUTOPR
XCHG
CALL PUTRND
LDA PSWFL
ORA A
CNZ XAHAL
CALL SEP ; SP,EP,SP or CR, LF, HT
LXI H,OPSAHF
CALL PUTRND
XCHG
JMP PUTEND
;
OPSAHF DB 'SAHF',0
;
; LXI rp,nn -> MOV rp',OFFSET nn
;
DOLXI: CALL PUTOPHT
LHLD xOPRND
CALL TRNRP
JNZ PUTOPR
LDAX D
CPI 'A'
JZ PUTOPR
XCHG
CALL PUTRND
LXI H,OFFATR
CALL PUTLIN
XCHG ; HL -> next
INX H ; skip comma
JMP PUTEND
;
OFFATR DB ',OFFSET ',0
;
; Translate 16 bit registers.
; Enter with HL -> rp.
; Returns HL -> next char, DE -> translation,
; Z set if match,
; otherwise, HL unchanged, NZ.
;
TRNRP: XRA A
STA LCDFLG
MOV A,M
CPI 'a'
JC TRNRP1
STA LCDFLG
TRNRP1: ANI 5FH
CPI 'B'
JZ TRNRPB
CPI 'D'
JZ TRNRPD
CPI 'H'
JZ TRNRPH
CPI 'P'
JZ TRNRPP
CPI 'S'
JZ TRNRPS
TRNRP2: MVI A,0
STA LCDFLG
RET
;
TRNRPB: LXI D,OPRCX ;'CX'
INX H
RET
;
TRNRPD: LXI D,OPRDX ;'DX'
INX H
RET
;
TRNRPH: LXI D,OPRBX ;'BX'
INX H
RET
;
TRNRPP: INX H
MOV A,M
ANI 5FH
CPI 'S'
JNZ TRNRP4
INX H
MOV A,M
ANI 5FH
CPI 'W'
JNZ TRNRP3
LXI D,OPRAX ;'AX'
INX H
RET
;
TRNRP3: DCX H
TRNRP4: DCX H
JMP TRNRP2
;
TRNRPS: INX H
MOV A,M
ANI 5FH
CPI 'P'
JNZ TRNRP4
LXI D,OPRSP
INX H
RET
;
OPRAX DB 'AX',0
OPRCX DB 'CX',0
OPRDX DB 'DX',0
OPRBX DB 'BX',0
OPRSP DB 'SP',0
;
; Strange opcodes
;
DOTDL: LDA OPCBUF+1
LXI H,CCZ ;'Z '
CPI 'E'
JZ DOTDL1
LXI H,CCNZ ;'NZ'
CPI 'N'
JZ DOTDL1
LXI H,CCC ;'C '
CPI 'L'
JZ DOTDL1
LXI H,CCNC ;'NC'
CPI 'G'
JZ DOTDL1
LXI H,CCZL
CPI 'e'
JZ DOTDL1
LXI H,CCNZL
CPI 'n'
JZ DOTDL1
LXI H,CCCL
CPI 'l'
JZ DOTDL1
LXI H,CCNCL
DOTDL1: MOV A,M
STA OPCBUF+1
INX H
MOV A,M
STA OPCBUF+2
RET
;
CCZ DB 'Z '
CCNZ DB 'NZ'
CCC DB 'C '
CCNC DB 'NC'
CCZL DB 'z '
CCNZL DB 'nz'
CCCL DB 'c '
CCNCL DB 'nc'
;
; Return conditional
; RC -> JNC $+3, RET
;
DORET: CALL PUTOPC
CALL PUTHT ; Could be PUTHTS
LXI H,REL3
CALL PUTLIN
CALL SEP
LXI H,OPRET
CALL PUTOPS
JMP PUTOPR
;
REL3 DB '$+3',0
OPRET DB 'RET',0
;
; Call conditional
; CC label -> JNC $+5, CALL label
;
DOCALL: CALL PUTOPC
CALL PUTHT ; Could be PUTHTS
LXI H,REL5
CALL PUTLIN
CALL SEP ; SP,EP,SP or CR, LF, HT
LXI H,OPCALL
CALL PUTOPS
CALL PUTHTS
JMP PUTOPR
;
REL5 DB '$+5',0
OPCALL DB 'CALL',0
;
; Jump conditional
; JC label -> JNC $+5, JMP label
;
DOJMP: CALL PUTOPC
CALL PUTHT ; Could be PUTHTS
LXI H,REL5
CALL PUTLIN
CALL SEP ; SP,EP,SP or CR, LF, HT
LXI H,OPJMP
CALL PUTOPS
CALL PUTHTS
JMP PUTOPR
;
OPJMP DB 'JMP',0
;
; IN n -> IN AL,n
;
DOIN: JMP DOIMM
;
; LDA addr -> MOV AL,addr
;
DOLDA: JMP DOIMM
;
; XCHG BX,rp'
; LDAX rp -> MOV AL,[BX]
; XCHG BX,rp'
;
DOLDAX: LHLD xOPRND
CALL TRNRP ; DE -> trans, HL -> next
JNZ PUTCOD
PUSH H
LXI H,OPXCHG
CALL PUTOPS
CALL PUTHTS
LXI H,OPBXC
CALL PUTOPS
XCHG
PUSH H
CALL PUTRND
CALL SEP ; SP,EP,SP or CR, LF, HT
LXI H,OPMOV
CALL PUTOPS
CALL PUTHTS
LXI H,OPLDAX
CALL PUTOPS
CALL SEP ; SP,EP,SP or CR, LF, HT
LXI H,OPXCHG
CALL PUTOPS
CALL PUTHTS
LXI H,OPBXC
CALL PUTOPS
POP H ; HL -> rp'
CALL PUTRND
POP H
JMP PUTEND
;
OPMOV DB 'MOV',0
OPLDAX DB 'AL,[BX]',0
;
; LHLD addr -> MOV BX,addr
;
DOLHLD: CALL PUTOPHT
LXI H,OPBXC ; 'BX,'
CALL PUTOPS
JMP PUTOPR
;
; OUT n -> OUT n,AL
;
DOOUT: CALL PUTOPHT
CALL PUTEXP
PUSH H
LXI H,OPCAL ; ',AL'
JMP DOSTA1
;
; PCHL -> JMP BX
;
DOPCHL: CALL PUTOPHT
LXI H,OPRBX ; 'BX'
CALL PUTOPS
JMP PUTOPR
;
; RST -> CALL 8*
;
DORST: CALL PUTOPHT
LXI H,OPR8M ;'8*'
CALL PUTOPS
JMP PUTOPR
;
OPR8M DB '8*',0
;
; SHLD addr -> MOV addr,BX
;
DOSHLD: CALL PUTOPHT
CALL PUTEXP
PUSH H
LXI H,OPCBX ; ',BX'
JMP DOSTA1
;
OPCBX DB ',BX',0
;
; SPHL -> MOV SP,BX
;
DOSPHL: CALL PUTOPHT
LXI H,OPSPBX ; 'SP,BX'
CALL PUTOPS
JMP PUTOPR
;
OPSPBX DB 'SP,BX',0
;
; STA addr -> MOV addr,AL
;
DOSTA: CALL PUTOPHT
CALL PUTEXP
PUSH H
LXI H,OPCAL ; ',AL'
DOSTA1: CALL PUTOPS
POP H
JMP PUTEND
;
OPCAL DB ',AL',0
;
; XCHG BX,rp'
; STAX rp -> MOV [BX],AL
; XCHG BX,rp'
;
DOSTAX: LHLD xOPRND
CALL TRNRP ; DE -> trans, HL -> next
JNZ PUTCOD
PUSH H
LXI H,OPXCHG
CALL PUTOPS
CALL PUTHTS
LXI H,OPBXC
CALL PUTOPS
XCHG
PUSH H
CALL PUTRND
CALL SEP ; SP,EP,SP or CR, LF, HT
LXI H,OPMOV
CALL PUTOPS
CALL PUTHTS
LXI H,OPSTAX
CALL PUTOPS
CALL SEP ; SP,EP,SP or CR, LF, HT
LXI H,OPXCHG
CALL PUTOPS
CALL PUTHTS
LXI H,OPBXC
CALL PUTOPS
POP H ; HL -> rp'
CALL PUTRND
POP H
JMP PUTEND
;
OPSTAX DB '[BX],AL',0
;
; XCHG -> XCHG BX,DX
;
DOXCHG: CALL PUTOPHT
LXI H,OPBXDX ; 'BX,DX'
CALL PUTOPS
JMP PUTOPR
;
OPBXDX DB 'BX,DX',0
;
; XCHG SP,BP
; XTHL -> XCHG [BP],BX
; XCHG SP,BP
;
DOXTHL: LXI H,OPXCHG
CALL PUTOPS
CALL PUTHTS
LXI H,OPSPBP ; 'SP,BP'
CALL PUTOPS
CALL SEP ; SP,EP,SP or CR, LF, HT
LXI H,OPXCHG
CALL PUTOPS
CALL PUTHTS
LXI H,OPXTHL
CALL PUTOPS
CALL SEP ; SP,EP,SP or CR, LF, HT
LXI H,OPXCHG
CALL PUTOPS
CALL PUTHTS
LXI H,OPSPBP
CALL PUTOPS
JMP PUTOPR
;
OPSPBP DB 'SP,BP',0
OPXTHL DB '[BP],BX',0
;
; CMA -> NOT AL
;
DOCMA: CALL PUTOPHT
LXI H,ALREG
CALL PUTOPS
JMP PUTOPR
;
; Put 'expression' to output file.
; 'expression' is everything between
; (xOPRND) up to the tab or spaces before
; a ';' or CR.
;
PUTEXP: LHLD xOPRND
PUTEX1: MOV A,M
CPI ';'
JZ PUTEX4
CPI CR
JZ PUTEX4
CPI '!'
JZ PUTEX3
PUTEX2: INX H
JMP PUTEX1
PUTEX3: DCX H
MOV A,M
INX H
CPI ' '
JZ PUTEX4
CPI HT
JZ PUTEX4
JMP PUTEX2
;
PUTEX4: DCX H
MOV A,M
CPI ' '
JZ PUTEX4
CPI HT
JZ PUTEX4
INX H
XCHG
LHLD xOPRND
PUTEX5: MOV A,D
CMP H
JNZ PUTEX6
MOV A,E
CMP L
RZ
PUTEX6: MOV A,M
CALL PUTCHR
INX H
JMP PUTEX5
;
; IFC -> IF
;
DOIFC: MVI A,HT
STA ENDIFL
JMP DOUPS
;
; ICL -> *INCL
;
DOICL: MVI A,HT
STA ICLFLG
JMP DOUPS
;
; LST -> LIST
;
DOLST: MVI A,HT
STA LSTFLG
JMP DOUPS
;
; MAC -> MACRO
;
DOMAC: MVI A,HT
STA MACFLG
DOUPS: CALL PUTOPHT
MVI A,CR
STA UPSMSG
JMP PUTOPR
;*******************************************************
;
; File operations
;
;*******************************************************
;
; Set up input and output FCB's from DFCB
;
MAKFNS: LXI H,DFCB1
LXI D,INFCB
LXI B,FNLEN+1
CALL MOVIR
MOV A,M ; typ specified ?
CPI ' '
JZ MKFNS1
CPI '?'
JZ MKFNS1
LXI B,3
CALL MOVIR
MKFNS1:
LXI H,DFCB1
LXI D,OUTFCB
LXI B,FNLEN+1
CALL MOVIR
LDA DFCB2 ;
ORA A ; allows output to
JZ MKFNS2 ; different drive
STA OUTFCB ; than input
MKFNS2:
LDA DFCB2+1 ;
CPI ' ' ;
JZ MKFNS3 ; allows output
LXI B,8 ; file to have
LXI D,OUTFCB+1 ; different name
LXI H,DFCB2+1 ; from input file
CALL MOVIR
MKFNS3:
LDA DFCB2+9
CPI ' '
JZ MKFNS4
LXI B,3
LXI D,OUTFCB+9
LXI H,DFCB2+9
CALL MOVIR
MKFNS4:
LXI D,PRFNM1
CALL PRTLIN
LXI H,INFCB
CALL PRFNAM
LXI D,PRFNM2
CALL PRTLIN
LXI H,OUTFCB
CALL PRFNAM
LXI D,CRLFMG
CALL PRTLIN
RET
;
; Print Filenames
;
PRFNAM: MOV A,M ; disk number
ORA A
JNZ PRFN1
LDA xCDISK
PRFN1: ADI '@'
CALL CONOUT
MVI A,':'
CALL CONOUT
INX H
MVI B,8
CALL PRFN
MVI A,'.'
CALL CONOUT
MVI B,3
PRFN: MOV A,M
INX H
CPI ' '
CNZ CONOUT
DCR B
JNZ PRFN
RET
;
PRFNM1 DB 'Source File: ',0
PRFNM2 DB ', Destination File: ',0
;
; Open source file with ext ASM
;
OPENIN:
LXI D,INFCB
MVI C,nOPEN
CALL BDOS
CPI NFF
JZ NSFERR
MVI A,RECLEN
LXI H,IBUFF+IBFLEN
SHLD xIBUFF
RET
;
NSFERR: LXI D,NSFMSG ;'No Source File'
JMP EREXIT
;
NSFMSG DB 'No Source File Found'
DB CR,LF,BEL,0
;
INFCB DB 0,0,0,0,0,0,0,0
DB 0,'ASM',0,0,0,0
DB 0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0
DB 0
;
; Create output file with ext Z80
;
CREATO:
LXI D,OUTFCB
MVI C,nOPEN
CALL BDOS
CPI NFF
JNZ OFEERR
CREAT4: LXI D,OUTFCB
MVI C,nCREAT
CALL BDOS
CPI NFF
JZ NDSERR
LXI D,OUTFCB
MVI C,nOPEN
CALL BDOS
MVI A,RECLEN
STA OBUFCT
LXI H,OBUFF
SHLD xOBUFF
RET
;
NDSERR: LXI D,NDSMSG ;'No directory space'
JMP EREXIT
;
NDSMSG DB 'No Directory Space'
DB CR,LF,BEL,0
;
OUTFCB DB 0,0,0,0,0,0,0,0
DB 0,'A86',0,0,0,0
DB 0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0
DB 0
;
;
OFEERR: LXI D,OFEMSG ;'Output file exists'
CALL PRTLIN
CALL CHKYES
JNZ ABORT
LXI D,OUTFCB
MVI C,nDEL
CALL BDOS
JMP CREAT4
;
OFEMSG DB 'Output File Already Exists'
DB ' -- Delete it and Continue ? (Y/N) '
DB BEL,0
;*******************************************************
;
; Put line at HL to output file until 0.
;
PUTLIN: MOV A,M
ANA A
RZ
CALL PUTCHR
INX H
JMP PUTLIN
;
; Put spaces or tabs at HL to output
; file until non-(space or tab)
;
PUTSPT: MOV A,M
CPI ' '
JZ PUTSP1
CPI HT
RNZ
PUTSP1: CALL PUTCHR
INX H
JMP PUTSPT
;
; Put statement separator to output file.
;
SEP: LHLD SEPMSG
JMP PUTLIN
;
SEPMSG DW NEWLSP
EXCLSP DB ' ! ',0
NEWLSP DB CR,LF,HT,0
;
; Put CR, LF to output file.
;
PCRLF: MVI A,CR
CALL PUTCHR
MVI A,LF
;
; Put char in A to output file,
; update column number.
;
PUTCHR: PUSH H
PUSH D
PUSH B
PUSH PSW
STA TEMP
LHLD xOBUFF
CPI EOT
JNZ PCHR0
MVI A,'!'
PCHR0: MOV M,A
CPI CR
JZ PUTCH0
CPI LF
JZ PUTCH0
CPI HT
JNZ PUTCH1
LDA COLNUM
DCR A
ANI NF8
ADI N09
JMP PUTCH2
PUTCH0: MVI A,1
JMP PUTCH2
;
PUTCH1: LDA COLNUM
INR A
PUTCH2: STA COLNUM
INX H ;inc obuff ptr
LDA OBUFCT
DCR A ;dec obuff count
JNZ PTCH21
MVI A,RECLEN
PTCH21: STA OBUFCT
MOV A,H
CPI (OBUFF+OBFLEN)/256
JNZ PUTCH4
MOV A,L
CPI (OBUFF+OBFLEN) MOD 256
JNZ PUTCH4
LXI D,OBUFF
PUTCH3:
MVI C,nDMA
PUSH D
CALL BDOS
POP D
XCHG
LXI D,OUTFCB
CALL WRTREC ;write record
LXI D,RECLEN
DAD D
XCHG
MOV A,D
CPI (OBUFF+OBFLEN)/256
JNZ PUTCH3
MOV A,E
CPI (OBUFF+OBFLEN) MOD 256
JNZ PUTCH3
LXI H,OBUFF
PUTCH4: SHLD xOBUFF
POP PSW
POP B
POP D
POP H
RET
;
TEMP DB 0
;
; Write record.
;
WRTREC: MVI C,nWRNR
PUSH H
CALL BDOS
POP H
ANA A
RZ
LXI D,OFWMSG ;'output file write error'
JMP EREXIT
;
OFWMSG DB 'Output File Write Error'
DB CR,LF,BEL,0
;
; Fill rest of obuff with EOF,
; write record, and close file.
;
CLOSEO: MVI A,EOF
CALL PUTCHR
LDA OBUFCT
CPI RECLEN
JNZ CLOSEO
;
CLOSE1:
LXI D,OBUFF
LHLD xOBUFF
MOV A,H
CMP D
JNZ CLOSE3
MOV A,L
CMP E
JNZ CLOSE3
CLOSE2:
LXI D,OUTFCB
MVI C,nCLOSE
JMP BDOS
;
CLOSE3: MVI C,nDMA
PUSH D
CALL BDOS
POP D
XCHG
LXI D,OUTFCB
CALL WRTREC
LXI D,RECLEN
DAD D
XCHG
LDA xOBUFF+1
CMP D
JNZ CLOSE3
LDA xOBUFF
CMP E
JNZ CLOSE3
JMP CLOSE2
;
; Print line at DE until 0
; on console.
;
PRTLIN: LDAX D
ANA A
RZ
CALL CONOUT
INX D
JMP PRTLIN
;
; Console Output character in A.
;
CONOUT: PUSH PSW
PUSH B
PUSH D
PUSH H
MOV E,A
MVI D,N00
MVI C,nCOUT
CALL BDOS
POP H
POP D
POP B
POP PSW
RET
;
; Get char from CONSOLE and return
; Z set if char.AND.5FH = 'Y'
;
CHKYES: MVI C,nCIN
CALL BDOS
PUSH PSW
CALL CRLF
POP PSW
ANI 5FH
CPI 'Y'
RET
;
; Return Z if no char available,
; otherwise, get char in A.
;
CHKIN: MVI C,nCDAV
CALL BDOS
ORA A
RZ
MVI C,nCIN
CALL BDOS
RET
;
;
;
CRLF: LXI D,CRLFMG
JMP PRTLIN
;
CRLFMG DB CR,LF,0
;
; Convert upper to lower case in A.
;
LCASE: CPI 'A'
RC
CPI 'Z'+1
RNC
ORI 20H
RET
;
; Convert lower case to upper case in A.
;
UCASE: CPI 'a'
RC
CPI 'z'+1
RNC
ANI 5FH
RET
;
; Print activity dot every 100 lines.
;
PDOT: LDA LNCNT
DCR A
STA LNCNT
RNZ
MVI A,'.'
CALL CONOUT
MVI A,100 ; Dot every 100 lines
STA LNCNT
LDA DOTCNT
DCR A
STA DOTCNT
JNZ PDOT1
MVI A,' '
CALL CONOUT
MVI A,10 ; Space every 10 dots
STA DOTCNT
PDOT1: LDA NLCNT
DCR A
STA NLCNT
RNZ
CALL CRLF
MVI A,50 ; 50 dots per line
STA NLCNT
RET
;
LNCNT DB 100 ; dot every 100 lines
DOTCNT DB 10 ; space every 10 dots
NLCNT DB 50 ; 50 dots per line
;
; Uninitialized storage.
;
xCDISK DS 1
SPBDOS DS 2
DS STCKLN
STACK EQU $
COLNUM DS 1
xOPCOD DS 2
OPCBUF DS OPBFLN
xOPRND DS 2
xOBUFF DS 2
OBUFCT DS 1
OBUFF DS OBFLEN
LBUFF DS LBUFLN+3
xIBUFF DS 2
IBUFF DS IBFLEN
END START
;
CLOSEO: MVI A,EOF
CALL PUTCHR
LDA OBU